import java.util.*;

//定义一个mapComparator类，该类实现了Comparator接口，用于排序
class mapComparator implements Comparator<Map.Entry<String,Integer>>{
    public int compare(Map.Entry<String,Integer> m1,Map.Entry<String,Integer> m2){
        //根据单词的出现频率进行降序排序
        if(m1.getValue()==m2.getValue()){
            return 0;
        }else {
            return (m1.getValue()>m2.getValue()?-1:1);
        }
    }
}

public class CountWords {
    public static void main(String[] args) {
        //定义一个Scanner类的对象，用于获取键盘中输入的内容
        Scanner scanner = new Scanner(System.in);
        //引导用户输入一个字符串
        System.out.println("Please input a string: ");
        //为从键盘中读入的字符串创建一个字符串分析器，以空格、逗号、句号、括号作为分隔符。
        StringTokenizer stringTokenizer = new StringTokenizer(scanner.nextLine(),"[' ',.()+]");
        //调用字符串分析器的countTokens()方法获取输入的字符串中的单词个数
        System.out.println("there are "+stringTokenizer.countTokens()+" words.");

        //将文章中的单词逐个拿出来放到HashMap中
        HashMap<String,Integer> hashtable = new HashMap<String,Integer>();//定义一个HashMap，将单词作为键，出现次数作为值
        while(stringTokenizer.hasMoreTokens()){//调用hasMoreTokens()判断字符串分析器中是否还有单词
            String word = stringTokenizer.nextToken();//调用nextToken()获取字符串分析器中的下一个单词
            word = word.toLowerCase(Locale.ROOT);//调用toLowerCase(Locale.ROOT)方法将单词中的大写字母转化为小写字母
            if(hashtable.containsKey(word)) {//如果hashtable中已经有和word相同的键值，说明该单词重复出现
                hashtable.put(word,hashtable.get(word)+1);//将hashtable中相应单词的值加一，以记录单词出现次数
            }else{//如果hashtable中没有和word相同的键值，说明该单词第一次出现
                hashtable.put(word, 1);//将该单词put到hashtable中，出现次数记为1
            }
        }

        //将hashtable中的键值数据对作为一个整体放到List创建的对象list中
        List<Map.Entry<String,Integer>> mapList = new ArrayList<Map.Entry<String, Integer>>(hashtable.entrySet());
        mapList.sort(new mapComparator());//通过比较器mapComparator的对象对mapList进行降序排序

        //遍历mapList的前五十个元素，将前50个元素依次输出
        for (int i = 0; i < 5; i++) {//共输出5行
            for (int j = 0; j < 10; j++) {//每行输出10个单词
                String word = (mapList.get(i*10+j)).getKey();//获取单词
                Integer count = (mapList.get(i*10+j)).getValue();//获取出现次数
                System.out.print("["+word+":"+count+"] ");//以[单词:次数]的形式输出
            }
            System.out.println();
        }
    }
}